import 'dart:io';

import 'package:dio/dio.dart';
import 'package:jtsell_app/entity_factory.dart';
import 'dart:async';
import 'dart:convert';
import '../exception/app_exception.dart';
import 'http_reslut.dart';

class HttpUtils<T> {
  HttpUtils();

  ///
  /// 获取公共的Dio对象
  /// 便于统一管理
  ///
  Dio _getCommonDio() {
    /// 全局属性：请求前缀、连接超时时间、响应超时时间
    BaseOptions options = new BaseOptions(connectTimeout: 300000, receiveTimeout: 300000);
    options.responseType = ResponseType.plain;
    Dio dio = new Dio(options);

    (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
      client.badCertificateCallback = (X509Certificate cert, String host, int port) {
        return true;
      };
    };

    (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
        (HttpClient client) {
      client.findProxy = (uri) {
        //proxy all request to localhost:8888
        return "PROXY 192.168.101.86:8888";
      };
      client.badCertificateCallback =
          (X509Certificate cert, String host, int port) => true;
    };

//    dio.interceptors
//        .add(InterceptorsWrapper(onRequest: (RequestOptions options) {
//      // 在请求被发送之前做一些事情
//      //continue
//      return options;
//      // 如果你想完成请求并返回一些自定义数据，可以返回一个`Response`对象或返回`dio.resolve(data)`。
//      // 这样请求将会被终止，上层then会被调用，then中返回的数据将是你的自定义数据data.
//      //
//      // 如果你想终止请求并触发一个错误,你可以返回一个`DioError`对象，或返回`dio.reject(errMsg)`，
//      // 这样请求将被中止并触发异常，上层catchError会被调用。
//    }, onResponse: (Response response) {
//      return response;
//    }, onError: (DioError e) {
//      // 当请求失败时做一些预处理
//      return e; //continue
//    }));

    return dio;
  }

  HttpResult<T> _getHttpResult(Map<String, dynamic> responseData) {
    HttpResult result = HttpResult<T>.parseData(responseData);

    if (result == null) {
      ///解析HttpReslut对象错误
      throw AppException(message: "json 解析失败");
    } else if (result.code != HttpResult.HTTP_STATUS_OK) {
      ///返回错误状态
      throw AppException(code: result.code, message: result.message);
    }

    return result; // continue
  }

  ///
  /// 简单的json直接转换成对象
  ///
  Future<HttpResult<T>> getParseHttpResult(String url,
      {Map<String, dynamic> queryParameters}) async {
    try {
      Response response = await _getCommonDio().get(url, queryParameters: queryParameters);

      Map<String, dynamic> responseData = json.decode(response.data.toString());
      return _getHttpResult(responseData);
    } on DioError catch (e) {
      if (e.type == DioErrorType.CONNECT_TIMEOUT || e.type == DioErrorType.RECEIVE_TIMEOUT) {
        throw AppException(message: "请求超时,请稍后重试");
      } else {
        String errMsg = e.error.message == null ? "请求错误,请稍后重试" : e.error.message;
        throw AppException(message: errMsg);
      }
    } on Exception catch (e) {
      throw AppException(message: "服务器连接错误,请稍后重试");
    }
  }

  ///
  /// post请求
  ///
  Future<HttpResult<T>> postParseHttpResult(String url,
      {Map<String, dynamic> queryParameters, dynamic data}) async {
    try {
      Response response =
          await _getCommonDio().post(url, queryParameters: queryParameters, data: data);

      Map<String, dynamic> responseData = json.decode(response.data.toString());
      return _getHttpResult(responseData);
    } on DioError catch (e) {
      if (e.type == DioErrorType.CONNECT_TIMEOUT || e.type == DioErrorType.RECEIVE_TIMEOUT) {
        throw AppException(message: "请求超时,请稍后重试");
      } else {
        String errMsg = e.error.message == null ? "请求错误,请稍后重试" : e.error.message;
        throw AppException(message: errMsg);
      }
    } on Exception catch (e) {
      throw AppException(message: "服务器连接错误,请稍后重试");
    }
  }

  ///
  /// post请求,直接转换成实体类
  ///
  Future<T> postParseEntity(String url,
      {Map<String, dynamic> queryParameters, dynamic data}) async {
    try {
      Response response =
          await _getCommonDio().post(url, queryParameters: queryParameters, data: data);

      if (T.toString() == "dynamic" || T.toString() == "String") {
        return response.data.toString() as T;
      }

      Map<String, dynamic> responseData = json.decode(response.data.toString());
      return EntityFactory.generateOBJ<T>(responseData);
    } on DioError catch (e) {
      if (e.type == DioErrorType.CONNECT_TIMEOUT || e.type == DioErrorType.RECEIVE_TIMEOUT) {
        throw AppException(message: "请求超时,请稍后重试");
      } else {
        String errMsg = e.error.message == null ? "请求错误,请稍后重试" : e.error.message;
        throw AppException(message: errMsg);
      }
    } on Exception catch (e) {
      throw AppException(message: "服务器连接错误,请稍后重试");
    }
  }
}
